package com.example.util;

import com.example.constant.BodyTypeConstant;
import com.example.constant.MessageConstant;
import com.example.constant.MessageTypeConstant;
import com.example.entity.body.Body;
import com.example.entity.body.impl.ASDUBody;
import com.example.entity.body.impl.InitBody;
import com.example.entity.header.Header;
import com.example.entity.message.Message;
import com.example.entity.message.impl.InitMessage;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class EncodeUtil {
	/**
	 * 先判断body是否为空，空则为U Message 否则 判断bodytype 是否为握手报文 不是，进行asdu判断报文类型
	 * 
	 * @param message
	 *            信息对象
	 * @return 写好的缓存
	 */
	public static ByteBuf encode(Message message) {

		System.out.println("调用了解析方法");
		ByteBuf buf = null;
		Body body = message.getBody();

		if (body == null) {
			buf = encodeU(message);
			return buf;
		}

		if (body.getBodyType() == BodyTypeConstant.INIT) {
			System.out.println("解析握手报文");
			buf = encodeINIT(message);
		} else if (body.getBodyType() == BodyTypeConstant.ASDU) {
			byte type = ((ASDUBody) body).getType();
			switch (type) {
			case MessageTypeConstant.CALLED_MESSAGE:
				System.out.println("解码总召报文");
				buf = encodeCall(message);
				break;
			case MessageTypeConstant.COUNT_MESSAGE:
				System.out.println("解码技术量总召");
				buf = encodeCountStart(message);
				break;
			case MessageTypeConstant.TIME_SYN_MESSAGE:
				System.out.println("时间同步解析");
				buf = encodeTimeSyn(message);
				break;
			default:
				break;
			}
		}

		return buf;

	}

	private static ByteBuf encodeINIT(Message message) {

		InitMessage initMessage = (InitMessage) message;
		Header header = initMessage.getHeader();
		InitBody body = (InitBody) initMessage.getBody();

		ByteBuf buf = Unpooled.buffer(header.getContextLength() + 3);

		buf.writeByte(0x68);
		buf.writeChar(header.getContextLength());

		buf.writeChar(body.getType());
		buf.writeLong(body.getCostModelID());
		buf.writeLong(body.getEquipmentID());
		buf.writeByte(body.getElectricPortNum());
		buf.writeByte(body.getElectricModel());
		buf.writeChar(body.getAddr());
		buf.writeByte(MessageConstant.BODY_END_TYPE);

		return buf;

	}

	private static ByteBuf encodeU(Message message) {
		ByteBuf buf = Unpooled.buffer(7);
		Header header = message.getHeader();

		buf.writeByte(0x68);
		buf.writeChar(header.getContextLength());
		buf.writeInt(header.getUControlField());
		buf.writeByte(MessageConstant.BODY_END_TYPE);

		return buf;
	}

	private static ByteBuf encodeCall(Message message) {
		ByteBuf buf = Unpooled.buffer();
		Header header = message.getHeader();

		header.write(buf);

		ASDUBody body = (ASDUBody) message.getBody();
		body.write(buf);

		return buf;
	}

	private static ByteBuf encodeCountStart(Message message) {
		ByteBuf buf = Unpooled.buffer(message.getHeader().getContextLength() + 3);
		Header header = message.getHeader();

		header.write(buf);

		ASDUBody body = (ASDUBody) message.getBody();
		body.write(buf);

		return buf;
	}

	private static ByteBuf encodeTimeSyn(Message message) {
		ByteBuf buf = Unpooled.buffer(message.getHeader().getContextLength() + 3);
		Header header = message.getHeader();

		header.write(buf);
		ASDUBody body = (ASDUBody) message.getBody();
		body.write(buf);

		return buf;
	}

	private static ByteBuf encodeRemoteElectricMessage(Message message) {
		ByteBuf buf = Unpooled.buffer(message.getHeader().getContextLength() + 3);
		Header header = message.getHeader();

		header.write(buf);
		ASDUBody body = (ASDUBody) message.getBody();
		body.write(buf);

		return buf;
	}

	public static byte[] BCDEncode(String str) {
		char[] cs = str.toCharArray();
		for (int i = 0; i < cs.length; i++) {
			cs[i] -= 48;
		}
		int bcdLength = 0;
		if (cs.length % 2 == 0) {
			bcdLength = cs.length / 2;
		} else {
			bcdLength = (cs.length + 1) / 2;
		}

		byte[] bcd = new byte[bcdLength];
		for (int i = bcdLength - 1, j = cs.length - 1; j >= 0; i--, j -= 2) {
			cs[j - 1] <<= 4;
			cs[j] |= cs[j - 1];
			bcd[i] = (byte) cs[j];
		}
		return bcd;
	}

}
